home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2.sit
/
Raven 1.2
/
Source
/
Foundation
/
OS
/
ZBootStrap.cpp
< prev
next >
Wrap
Text File
|
1997-08-16
|
9KB
|
382 lines
/*
* File: ZBootStrap.cpp
* Summary: An object used to initialize and terminate an application.
* Written by: Jesse Jones
*
* Copyright ゥ 1996-1997 Jesse Jones.
* For conditions of distribution and use, see copyright notice in ZTypes.h
*
* Change History (most recent first):
*
* <8> 8/16/97 JDJ Boot calls InitContextualMenus.
* <7> 8/06/97 JDJ Sucky Mac alert uses StandardAlert. OnSystemNeeds
* uses REQUIRES_APPEARANCE_MGR.
* <6> 8/03/97 JDJ Calls RegisterAppearanceClient.
* <5> 6/20/97 JDJ FragInit traps exceptions.
* <4> 4/13/97 JDJ FragTerm calls MExitAction::DoExitActions().
* <3> 3/27/97 JDJ Commented out call to __destroy_global_chain
* (MSL C++ 2.1.1 calls it for us).
* <2> 3/24/97 JDJ Dtor checks for CW 11.1
* <1> 10/27/96 JDJ Created (from ZAppBootStrap)
*/
#include <ZBootStrap.h>
#include <Appearance.h>
#include <CodeFragments.h>
#include <ContextualMenu.h>
#include <Dialogs.h>
#include <Fonts.h>
#include <List.h>
#include <TextEdit.h>
#include <ZConstants.h>
#include <ZDebug.h>
#include <ZExceptions.h>
#include <ZExitAction.h>
#include <ZGestalt.h>
#include <ZMiscUtils.h>
#include <ZStringUtils.h>
#if RAVEN_OPERATOR_NEW
#include <ZMemoryHeap.h>
#include <ZNewAndDelete.h>
#endif
//-----------------------------------
// Static Globals
//
static bool sInited = false;
// ===================================================================================
// Internal Functions
// ===================================================================================
extern "C" void __destroy_global_chain();
//---------------------------------------------------------------
//
// InitializeToolbox
//
//---------------------------------------------------------------
static void InitializeToolbox()
{
MaxApplZone(); // MoreMasters should be called in DoEarlyInit
InitGraf((Ptr) &qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
}
//---------------------------------------------------------------
//
// FragInit
//
// Entry point for the application's fragment. This is called
// before static constructors, so it's a good place to perform
// any critical initialization.
//
//---------------------------------------------------------------
#pragma profile off
extern "C" OSErr FragInit(CFragInitBlock);
OSErr FragInit(CFragInitBlock block)
{
#pragma unused(block)
OSStatus err = noErr;
InitializeToolbox();
try {
TBootStrap::DoEarlyInit();
#if RAVEN_OPERATOR_NEW
ASSERT(gObjectHeap != nil); // Create this in DoEarlyInit
#endif
sInited = true;
// ・・・ハNote that these catch blocks are never executed: if an
// ・・・ハexception is thrown the program immediately terminates.
// ・・・ハI think this is happening because FragInit is called
// ・・・ハbefore __start has a chance to initialize the exception
// ・・・ハcode. I experimented with calling __register_fragment
// ・・・ but then throw did nothing and the app crashed.
#if 0
} catch (const TMemoryException& e) {
ReportError(LoadRavenString("Initialization failed because"), e);
err = memFullErr;
} catch (const TSystemException& e) {
ReportError(LoadRavenString("Initialization failed because"), e);
err = e.mError;
} catch (const TBaseException& e) {
ReportError(LoadRavenString("Initialization failed because"), e);
err = -1;
} catch (...) {
ReportError(LoadRavenString("Initialization failed because of an unknown error"));
err = -1;
}
#else
} catch (const TSystemException& e) {
err = e.mError;
} catch (...) {
err = -1;
}
#endif
return (OSErr) err;
}
#pragma profile reset
//---------------------------------------------------------------
//
// FragTerm
//
// Exit point for the application's fragment. This is called
// after static constructors, so it's a good place to do leak
// checking.
//
//---------------------------------------------------------------
#pragma profile off
extern "C" void FragTerm();
void FragTerm()
{
// The release notes for System 7.6 say that A5 can be incorrect
// for earlier Systems when ExitToShell is called. To avoid any
// problems we'll make sure A5 is correct.
long oldA5 = SetCurrentA5();
if (TBootStrap::Exiting()) { // don't bother with leaks if we're terminating abnormally
#if DEBUG
ulong leaks = 0;
#if RAVEN_OPERATOR_NEW
leaks = gObjectHeap->GetLeakCount();
if (leaks > 0)
gObjectHeap->DumpLeaks();
#elif DEBUG_NEW > DEBUG_NEW_BASIC
leaks = gDebugNewAllocCount;
if (leaks > 0)
DebugNewReportLeaks();
#endif
if (leaks > 0)
DEBUGSTR("You have %d memory leaks: check the leaks.log file.", leaks);
#endif
} else
MExitAction::DoExitActions(); // terminating abnormally so call exit actions
SetA5(oldA5);
}
#pragma profile reset
//---------------------------------------------------------------
//
// MyNewHandler
//
// ・・・ハRemove this when new throws and we can move to ANSI exceptions.
//
//---------------------------------------------------------------
static void MyNewHandler()
{
throw TMemoryException();
}
#pragma mark -
// ===================================================================================
// class TBootStrap
// ===================================================================================
bool TBootStrap::msRunning = false;
bool TBootStrap::msExiting = false;
//---------------------------------------------------------------
//
// TBootStrap::~TBootStrap
//
//---------------------------------------------------------------
TBootStrap::~TBootStrap()
{
msExiting = true; // terminating normally
msRunning = false;
// __destroy_global_chain(); // MSL C++ 2.1.1 handles this correctly
}
//---------------------------------------------------------------
//
// TBootStrap::TBootStrap
//
//---------------------------------------------------------------
TBootStrap::TBootStrap()
{
::FlushEvents(everyEvent, 0);
}
//---------------------------------------------------------------
//
// TBootStrap::Running [static]
//
//---------------------------------------------------------------
bool TBootStrap::Running()
{
return msRunning;
}
//---------------------------------------------------------------
//
// TBootStrap::Exiting [static]
//
//---------------------------------------------------------------
bool TBootStrap::Exiting()
{
return msExiting;
}
//---------------------------------------------------------------
//
// TBootStrap::Boot
//
//---------------------------------------------------------------
void TBootStrap::Boot()
{
ASSERT(sInited); // Need to use FragInit and FragTerm entry points!
InitCursor();
set_new_handler(MyNewHandler);
UGestalt::Init();
if (UGestalt::hasAppearanceMgr)
RegisterAppearanceClient();
if (UGestalt::hasContextMenus) {
OSStatus err = InitContextualMenus();
if (err != noErr) {
UGestalt::hasContextMenus = false;
DEBUGSTR("InitContextualMenus returned %d", err);
}
}
#ifdef __PowerPlant__
UQDGlobals::SetQDGlobals(&qd);
#endif
this->HandleSystemCheck();
this->OnBoot();
msRunning = true;
}
//---------------------------------------------------------------
//
// TBootStrap::HandleSystemCheck
//
//---------------------------------------------------------------
void TBootStrap::HandleSystemCheck()
{
list<string, allocator<string> > needs;
// Find out what the system is missing.
this->OnSystemNeeds(needs);
if (needs.size() > 0) {
// Build a string containing all of the reasons the app won't run.
string mesg;
if (needs.size() == 1)
mesg += needs.front();
else if (needs.size() == 2)
mesg += needs.front() + LoadRavenString(" and ") + needs.back();
else {
list<string, allocator<string> >::iterator iter = needs.begin();
while (iter != needs.end()) {
string item = *iter++;
if (iter == needs.end())
mesg += LoadRavenString("and ");
mesg += item;
if (iter != needs.end())
mesg += LoadRavenString(", ");
}
}
// Put up an alert to let the user know how badly their Mac sucks.
InitCursor();
if (UGestalt::hasAppearanceMgr) {
AlertStdAlertParamRec params;
params.movable = false;
params.helpButton = false;
params.filterProc = nil;
params.defaultText = StrToPStr(LoadRavenString("Quit"));
params.cancelText = nil;
params.otherText = nil;
params.defaultButton = ok;
params.cancelButton = 0;
params.position = kWindowDefaultPosition;
string errorStr = LoadRavenString("Unable to run the app.");
short item;
OSErr err = StandardAlert(kAlertStopAlert, StrToPStr(errorStr), StrToPStr(mesg), ¶ms, &item);
ASSERT(err == noErr); // seems kind of pointless to throw
} else {
ParamText(StrToPStr(mesg), "¥p", "¥p", "¥p");
(void) ::Alert(129, nil);
}
// Bail
::ExitToShell();
}
}
//---------------------------------------------------------------
//
// TBootStrap::OnSystemNeeds
//
//---------------------------------------------------------------
void TBootStrap::OnSystemNeeds(list<string, allocator<string> >& needs)
{
if (UGestalt::systemVersion < 0x00700)
needs.push_back(LoadRavenString("System 7"));
if (!UGestalt::hasColorQD)
needs.push_back(LoadRavenString("Color QuickDraw"));
#if REQUIRES_APPEARANCE_MGR
if (!UGestalt::hasAppearanceMgr)
needs.push_back(LoadRavenString("the Appearance Manager"));
#endif
}